﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using VMDS.Business.Entities;
using VMDS.GUIClient.Helper;
using VMDS.GUIClient.Model;

namespace VMDS.GUIClient.ViewModels.Management.Clients
{
    internal class ClientsManagementViewModel : BaseViewModel
    {
        private readonly BackgroundWorker _loader;
        private ClientPC _addPc;
        private ClientPC _pc;
        private ObservableCollection<ClientPC> _pcs;
        private ObservableCollection<ClientPC> _pcsad;
        private ObservableCollection<ClientPC> _pcsselected;
        private ObservableCollection<ClientPC> _pcstoadd;
        private bool _refl;
        private string _filter;
        private string _newname;

        private ObservableCollection<string> _online;
        public ObservableCollection<string> Online
        {
            get { return _online; }
            set { _online = value; OnPropertyChanged(() => Online); }
        }

        private ObservableCollection<string> _guests;
        public ObservableCollection<string> Guests
        {
            get { return _guests; }
            set { _guests = value; OnPropertyChanged(() => Guests); }
        }


        public ClientsManagementViewModel()
        {
            PCsToAdd = new ObservableCollection<ClientPC>();
            SelectedPCs = new ObservableCollection<ClientPC>();
            SelectedPCs.CollectionChanged += SelectedPCs_CollectionChanged;
            PCsToAdd.CollectionChanged += new NotifyCollectionChangedEventHandler(PCsToAdd_CollectionChanged);
            PCs = new ObservableCollection<ClientPC>();
            _loader = new BackgroundWorker();
            _loader.DoWork += loader_DoWork;
            _loader.RunWorkerAsync();
        }

        void PCsToAdd_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            OnPropertyChanged(()=>AddAllPc);
        }

        public ObservableCollection<ClientPC> SelectedPCs
        {
            get { return _pcsselected; }
            set
            {
                _pcsselected = value;
                OnPropertyChanged(() => SelectedPCs);
            }
        }

        public ObservableCollection<ClientPC> PCs
        {
            get { return _pcs; }
            set
            {
                _pcs = value;
                OnPropertyChanged(() => PCs);
            }
        }

        public ObservableCollection<ClientPC> PCsToAdd
        {
            get { return _pcstoadd; }
            set
            {
                _pcstoadd = value;
                OnPropertyChanged(() => PCsToAdd);
            }
        }

        void deletePc()
        {
            if (MessageBox.Show("Удалить " + CurrentPC.Name + "?", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                try
                {
                    ServiceLocator.MainService.RemovePC(CurrentPC);
                    PCs.Remove(CurrentPC);
                }
                catch
                {
                    MessageBox.Show("Ошибка удаления. Возможно, данному ПК назначены задания","",MessageBoxButton.OK,MessageBoxImage.Error);
                }
            }
        }
        public ICommand DeleteRequest
        {
            get { return new BaseCommand(deletePc, () => CurrentPC != null); }
        }

        public ClientPC CurrentPCtoADD
        {
            get { return _addPc; }
            set
            {
                _addPc = value;
                OnPropertyChanged(() => CurrentPCtoADD);
                OnPropertyChanged(()=>DeletePcToAdd);
            }
        }

        public string NewPcName
        {
            get { return _newname; }
            set { _newname = value;
                OnPropertyChanged(()=>NewPcName);
                OnPropertyChanged(() => AddNewPc);
            }
        }

        

        public ICommand AddNewPc
        {
            get { return new BaseCommand(() => { PCsToAdd.Add(new ClientPC() { Name = NewPcName });
                                                   NewPcName = "";}, 
                                                   () => !String.IsNullOrWhiteSpace(NewPcName)); }
        }

        void Add()
        {
            try
            {
                ServiceLocator.MainService.AddPCs(PCsToAdd.ToArray());
                getPCs();
                PCsToAdd.Clear();
            }
            catch (Exception exception)
            {ShowMessageBox("Произошла ошибка"); }
        }

        public ICommand AddAllPc
        {
            get { return new BaseCommand(Add,()=>PCsToAdd.Count>0); }
        }

        public ICommand DeletePcToAdd
        {
            get
            {
                return new BaseCommand(() => PCsToAdd.Remove(CurrentPCtoADD),() => CurrentPCtoADD != null);
            }
        }

        public ObservableCollection<ClientPC> AdPCs
        {
            get { return applyFilter(Filter); }
            set
            {
                _pcsad = value;
                OnPropertyChanged(() => AdPCs);
            }
        }

        public bool CanRefesh
        {
            get { return _refl; }
            set
            {
                _refl = value;
                OnPropertyChanged(() => CanRefesh);
            }
        }

        

        public ICommand Reflesh
        {
            get
            {
                return new BaseCommand(() =>
                                           {
                                               AdPCs.Clear();
                                               _loader.RunWorkerAsync();
                                           });
            }
        }

        public ICommand Import
        {
            get { return new BaseCommand(import, canImport); }
        }

        public string Filter
        {
            get { return _filter; }
            set
            {
                _filter = value;
                OnPropertyChanged(() => Filter);
                OnPropertyChanged(() => AdPCs);
            }
        }

        public ClientPC CurrentPC
        {
            get { return _pc; }
            set
            {
                _pc = value;
                OnPropertyChanged(() => CurrentPC);
                OnPropertyChanged(()=>DeleteRequest);
            }
        }

        private void SelectedPCs_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            OnPropertyChanged(() => Import);
        }

        private bool canImport()
        {
            return SelectedPCs.Count > 0;
        }


        private void import()
        {
            foreach (ClientPC pc in SelectedPCs)
            {
                if (PCsToAdd.Any(x => x.Name == pc.Name)) continue;
                PCsToAdd.Add(pc);
            }
        }

        private ObservableCollection<ClientPC> applyFilter(string s)
        {
            if (_pcsad == null) return new ObservableCollection<ClientPC>();
            if (String.IsNullOrWhiteSpace(s)) return _pcsad;
            return
                new ObservableCollection<ClientPC>(
                    _pcsad.Where(clientPc => clientPc.Name.ToLower().Contains(s.ToLower())));
        }

        private ObservableCollection<ClientPC> GetAdPcs()
        {
            var result = new ObservableCollection<ClientPC>();
            foreach (string Pc in AD.GetComputers())
            {
                result.Add(new ClientPC {Name = Pc});
            }
            return result;
        }

        void getPCs()
        {
            try
            {
                PCs = new ObservableCollection<ClientPC>(ServiceLocator.MainService.GetPCs());
            }
            catch { ShowMessageBox("ошибка получения данных");}
        }
        void monitoring()
        {
            try
            {
                Guests = new ObservableCollection<string>(ServiceLocator.MainService.GetUnknownPCs());
            }
            catch{}
            try
            {
                Online = new ObservableCollection<string>(ServiceLocator.MainService.GetOnlinePCs().Select(x => x.Name));
            }
            catch{}
        }

        private Timer timer;
        private void loader_DoWork(object sender, DoWorkEventArgs e)
        {
            CanRefesh = false;
            timer=new Timer();
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Interval = 20000;
            timer.Enabled=true;
            try
            {
                AdPCs = GetAdPcs();
                monitoring();
            }
            catch { }
            getPCs();
            CanRefesh = true;
        }

        void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            monitoring();
        }
    }
}